#include "TwOgreEnumVariable.h"

#include <sstream>

#include "TwOgreWindow.h"
#include "TwOgreWindowManager.h"

namespace TwOgre{
	EnumVariable::EnumVariable(Window *parent, const Ogre::String& name, bool readOnly, const Ogre::String& label, 
		const EnumValueList& enumList, int value, const Ogre::String& groupName, const Ogre::String& help) :
		Variable(parent, name, TW_TYPE_UNDEF), mValue(value)
	{
		int enumSize = static_cast<int>(enumList.size());
		TwEnumVal *enumValue = new TwEnumVal[enumSize];
		for(int i = 0; i < enumSize; i++)
		{
			enumValue[i].Value = enumList[i].first;
			enumValue[i].Label = enumList[i].second.c_str();
		}

		mVarType = TwDefineEnum(Ogre::String(mName+"Type").c_str(), enumValue, enumSize);

		if(readOnly)
		{
			TwAddVarRO(mParent->getTweakBar(), mName.c_str(), mVarType, &mValue, "");
		}
		else
		{
			TwAddVarRW(mParent->getTweakBar(), mName.c_str(), mVarType, &mValue, "");
		}

		if(label.compare("") != 0)
		{
			setLabel(label);
		}
		if(groupName.compare("") != 0)
		{
			setGroup(groupName);
		}
		if(help.compare("") != 0)
		{
			setHelp(help);
		}
	}

	EnumVariable::EnumVariable(EnumParams& params) :
        Variable(params.parent_, params.name_, params.type_), mValue(params.value_)
    {
        int enumSize = static_cast<int>(params.enumValues_.size());
		TwEnumVal *enumValue = new TwEnumVal[enumSize];
		for(int i = 0; i < enumSize; i++)
		{
			enumValue[i].Value = params.enumValues_[i].first;
			enumValue[i].Label = params.enumValues_[i].second.c_str();
		}

		mVarType = TwDefineEnum(Ogre::String(mName+"Type").c_str(), enumValue, enumSize);

        // add callbacks
        TwAddVarCB(mParent->getTweakBar(), mName.c_str(), mVarType, params.setCB_, params.getCB_, params.data_, "");

		if(params.readOnly_)
		{
			TwAddVarRO(mParent->getTweakBar(), mName.c_str(), mVarType, &mValue, "");
		}
		else
		{
			TwAddVarRW(mParent->getTweakBar(), mName.c_str(), mVarType, &mValue, "");
		}

		if(params.label_.compare("") != 0)
		{
			setLabel(params.label_);
		}
		if(params.group_.compare("") != 0)
		{
            setGroup(params.group_);
		}
        if(params.help_.compare("") != 0)
		{
            setHelp(params.help_);
		}
        if((params.shortcutIncr_.compare("") != 0) && (params.shortcutDecr_.compare("") != 0))
		{
            setShortcut(params.shortcutIncr_, params.shortcutDecr_);
		}
    }
	
    EnumVariable::~EnumVariable()
	{
		TwRemoveVar(mParent->getTweakBar(), mName.c_str());
	}

	void EnumVariable::addEnumValues(const EnumValueList& enumList)
	{
		std::stringstream ss;
		ss << " '" << mParent->getName() << "'/'" <<  mName << "' Val='";

		EnumValueList::const_iterator enumItr;
		for(enumItr = enumList.begin(); enumItr != enumList.end(); enumItr++)
		{
			ss << " " << enumItr->first << " {" << enumItr->second << "}, ";
		}
		
		ss << "' ";

		TwDefine(ss.str().c_str());
	}

	void EnumVariable::setShortcut(const Ogre::String& increment, const Ogre::String& decrement)
	{
		std::stringstream ss;
		ss << " '" << mParent->getName() << "'/'" <<  mName 
		   << "' KeyIncr='" << increment
		   << "' KeyDecr='" << decrement << "' ";

		TwDefine(ss.str().c_str());
	}
}; // End Namespace
